#include <emscripten/emscripten.h>
#include <emscripten/bind.h>
#include <emscripten/val.h>
#include "FileData.h"
#include "MyClass.h"
#include "DataType.h"

// 一旦WASM模块被加载，main()中的代码就会执行
int main(int argc, char **argv)
{
    printf("WebAssembly module loaded\n");
}

#ifdef __cplusplus
extern "C"
{
#endif

    // 返回1-6之间的一随机数
    EMSCRIPTEN_KEEPALIVE
    int roll_dice()
    {
        srand(time(NULL));
        return rand() % 6 + 1;
    }

    // 整形入参
    EMSCRIPTEN_KEEPALIVE
    int fibonacci_recursive(int n)
    {
        if (n <= 1)
            return n;
        return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2);
    }

    // 返回一个数组
    EMSCRIPTEN_KEEPALIVE
    char getChar()
    {
        static char a = 'A';
        return a;
    }

    // 返回一个指向数组的指针，并将数组大小存储到 `length` 中
    EMSCRIPTEN_KEEPALIVE
    int *getArray(int *length)
    {
        static std::vector<int> data = {1, 2, 3, 4, 5};
        *length = data.size();
        return data.data();
    }

#ifdef __cplusplus
}
#endif

// C++ 代码
// 根据参数类型，返回不同类型的数据
emscripten::val returnAnyTypeByParamsType(const std::string &str)
{
    emscripten::val res = emscripten::val::undefined();
    if (str.compare("int") == 0)
        res = emscripten::val(123);
    else if (str.compare("string") == 0)
        res = emscripten::val("abc");
    else if (str.compare("bool") == 0)
        res = emscripten::val(true);
    return res;
}

EMSCRIPTEN_BINDINGS(my_module)
{
    // 返回int
    emscripten::function("sum", &DataType::sum);
    // 注册vector
    emscripten::register_vector<int>("vector<int>");

    // 使用vector作为返回值
    emscripten::function("getVector", &DataType::32);

    // 注册 Struct
    emscripten::value_object<DataType::PersonRecord>("PersonRecord")
        .field("name", &DataType::PersonRecord::name)
        .field("age", &DataType::PersonRecord::age);
    // 使用 Struct 作为返回值
    emscripten::function("getUser", &DataType::getUser);
    emscripten::function("setUser", &DataType::setUser);

    // 注册函数
    emscripten::function("fileDataToBase64", &FileData::fileDataToBase64);

    // 注册函数
    emscripten::function("returnAnyTypeByParamsType", &returnAnyTypeByParamsType);

    // 注册Class
    emscripten::class_<MyClass>("MyClass")
        .constructor<int, std::string>()
        .function("incrementX", &MyClass::incrementX)
        .property("x", &MyClass::getX, &MyClass::setX)
        .property("x_readonly", &MyClass::getX)
        .class_function("getStringFromInstance", &MyClass::getStringFromInstance);
}